﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Collections;
using Nature.Data;

namespace Nature.Toolkit.GMix
{
    /// <summary>
    /// Collection of the MixProjection items 
    /// </summary>
    public class MixProjectionCollection : IEnumerable<MixProjection>
    {
        #region Private Members        

        ExpressionInfo m_expressionInfo;

        private MixProjectionEnumerator GetEnumerator()
        {
            return new MixProjectionEnumerator(m_expressionInfo);
        }

        #endregion

        #region Constructor
        /// <summary>
        /// Instantinates a new item of the MixProjectionCollection object
        /// </summary>
        /// <param name="expression">Mixture expression object</param>
        /// <param name="provider">Data provider object</param>
        public MixProjectionCollection(IExpression expression, System.Collections.IEnumerable entitiesHeap, MixSetupInfo setupInfo = null)
        {
            m_expressionInfo = new ExpressionInfo(expression, entitiesHeap, setupInfo);
        } 

        #endregion

        public ReadOnlyArray<string> ParametersNames
        {
            get { return m_expressionInfo.ParameterNames; }
        }

        public ReadOnlyArray<string> ComponentNames
        {
            get { return m_expressionInfo.ComponentNames; }
        }

        public ReadOnlyArray<string> SpeciesIDs
        {
            get { return m_expressionInfo.SpeciesIDs ; }
        }

        public ReadOnlyArray<int> RootComponentIndexes
        {
            get 
            { 
                var roots = m_expressionInfo.Components.Where(i=>i.IsRoot).Select(i=> i.ComponentName);
                return roots.Select(i=> m_expressionInfo.ComponentIndex(i)).ToArray(); 
            }
        }

        public XElement ToXElement()
        {
            XElement xel = new XElement("Mixture");
            XElement xelParams = new XElement("Parameters");
            XElement xelComponents = new XElement("Components");
            XElement xelSpecies = new XElement("Species");
            List<XElement> components = new List<XElement>();
            
            xel.Add(xelParams);
            xel.Add(xelComponents);
            xel.Add(xelSpecies);

            for (int ipa = 0; ipa < ParametersNames.Length; ++ipa )
            {
                xelParams.Add(
                        new XElement("Parameter", 
                            new XAttribute("Name", ParametersNames[ipa]) ),
                            new XAttribute("Index", ipa)
                    );
            }

            for (int isp = 0; isp < SpeciesIDs.Length; ++isp)
            {
                xelSpecies.Add(
                        new XElement("Spec",
                            new XAttribute("Name", SpeciesIDs[isp]),
                            new XAttribute("Index", isp))
                    );
            }

            for (int ico = 0; ico < ComponentNames.Length; ++ico)
            {
                XElement xc = new XElement("Component", 
                    new XAttribute("Name", ComponentNames[ico]));
                xelComponents.Add(xc);
                components.Add(xc);
            }



            IEnumerator<MixProjection> enumerator = GetEnumerator();
            while (enumerator.MoveNext())
            {
                var projection = enumerator.Current;
                for (int ico = 0; ico < projection.CompositionObjects.Length; ++ico)
                {
                    var composition = projection.CompositionObjects[ico];
                    var xc = components[ico];
                    XElement xm = new XElement("X");
                    xc.Add(xm);
                    for (int isp = 0; isp < composition.X.Length; ++isp)
                    {
                        xc.Add(
                                new XElement("X",
                                    new XAttribute("ID", SpeciesIDs[isp]),
                                    composition.X[isp]
                                    )
                            );
                    }
                }
            }

            return xel;
        }

        #region IEnumerable<MixEnumeratorContext> Members

        IEnumerator<MixProjection> IEnumerable<MixProjection>.GetEnumerator() { return this.GetEnumerator(); }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.GetEnumerator(); }

        #endregion
    }
}
